package com.example.utils.util;


import org.springframework.util.StopWatch;

/**
 * CRC16X25校验工具类  -  698协议
 */
public class CRC16X25Process {

    public static void main(String[] args) {
        // 初始化数据
//            byte[] data = new byte[]{0x17, 0x00, 0x43, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        long l = System.currentTimeMillis();

        String hexString = "17 00 43 05 01 00 00 00 00 00 00 a7 e6 05 01 01 00 00 02 00 00";
        String hexStringFromB = hexString.replace(" ", "");


//            String hexString = "1700430501000000000000";
        byte[] data = toBytes(hexStringFromB.trim());

        // 计算CRC
        int crc = calculateCRC16X25(data);
        System.out.println("CRC = " + crc);
        // 将CRC转换为两个字节
//            byte[] crcBytes = new byte[]{(byte) ((crc >> 8) & 0xFF), (byte) (crc & 0xFF)};
        // 将CRC转换为两个字节, 并进行高低位互换，输出符合相关工具对Modbus CRC16的运算
        byte[] crcBytes = new byte[]{(byte) (crc & 0xFF),(byte) ((crc >> 8) & 0xFF)};
        // 输出结果
        System.out.printf("CRC-16/X.25: %02X%02X%n", crcBytes[0], crcBytes[1]);
        String hexString1 = toHexString1(crcBytes);
        System.out.println(hexString1);

        long currentTimeMillis = System.currentTimeMillis();
        System.out.println(currentTimeMillis - l);
        stopWatch.stop();
        System.out.println(stopWatch.getTotalTimeSeconds());
    }

    public static byte[] toBytes(String str) {  //  aa  -->  0xaa
        if (str == null || "".equals(str.trim())) {
            return new byte[0];
        }

        byte[] bytes = new byte[str.length() / 2];
        for (int i = 0; i < str.length() / 2; i++) {
            String subStr = str.substring(i * 2, i * 2 + 2);
            bytes[i] = (byte) Integer.parseInt(subStr, 16);
        }

        return bytes;
    }
    public static String toHexString1(byte[] b) {
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < b.length; ++i) {
            buffer.append(toHexString1(b[i]));
        }
        String str = buffer.toString().substring(0, buffer.length());
        return str;
    }
    public static String toHexString1(byte b) {
        String s = Integer.toHexString(b & 0xFF);
        if (s.length() == 1) {
            return "0" + s;
        } else {
            return s ;
        }
    }
    public static int calculateCRC16X25(byte[] data) {
        int crc = 0xFFFF; // 初始化CRC寄存器为0xFFFF

        for (byte b : data) {
            crc ^= (b & 0xFF); // 将数据字节的每个位与CRC寄存器的每个位进行异或操作

            for (int i = 0; i < 8; i++) {
                if ((crc & 0x0001) != 0) {
                    crc >>= 1; // 将CRC寄存器右移一位
                    crc ^= 0x8408; // 与多项式0x8408进行异或操作
                } else {
                    crc >>= 1; // 将CRC寄存器右移一位
                }
            }
        }

        // 反转最终CRC值
        crc = ~crc;
        // 限制CRC值在16位范围内
        crc &= 0xFFFF;

        return crc;
    }

}
